#pragma once
#include "common.hpp"
#include <memory>
#include <functional>

// 定义抽象类提供接口
namespace Abstract
{
    // 消息基础类提供设置一条消息的各个元素的接口和把消息序列化和反序列化的接口
    // 和把不同的消息的相同的元素给抽取出来
    class BaseMessage
    {
    public:
        using MesaPtr = std::shared_ptr<BaseMessage>;
        ~BaseMessage() {} // 抽象类的虚函数必须要显示实现
        // 这样派生类继承下去后，如果使用智能指针是使用基类去接收派生类对象的指针智能
        // 将来这个智能时钟销毁时--delete ptr时会先去调用派生类的析构函数然后再去调用基类的析构函数
        // 这样不至于基类的资源造成泄漏
        //  设置消息类型
        virtual void SetMtype(Rs_RqType Mtype) { _Mtype = Mtype; }
        // 设置消息编号
        virtual void SetUuid(const std::string uuid) { _uuid = uuid; }
        virtual Rs_RqType GetMtype() { return _Mtype; }
        virtual std::string GetUuid() { return _uuid; }
        // 消息的序列化和反序列化
        virtual std::string Serialize() = 0;
        virtual bool UnSerialize(std::string &msg) = 0;
        // 校验json串
        virtual bool Check() = 0;

    private:
        Rs_RqType _Mtype;  // 请求类型
        std::string _uuid; // 消息编号
    };

    // 定义一个buffer基类来提供从网络层(read)读取的数据/消息的接口
    // 是基于muodu库的buffer对象
    class BaseBuffer
    {
    public:
        using BuffPtr = std::shared_ptr<BaseBuffer>;
        // 获取缓冲区的字节数
        virtual size_t ReadAllSize() = 0;
        // 尝试从缓冲区读取4字节，但是缓冲区不删除读取的数据
        virtual int32_t Peek_4Byte() = 0;
        // 删除缓冲区4字节数据
        virtual void Delete_4Byte() = 0;
        // 读取4字节并且从缓冲区删除
        virtual int32_t Read_4Byte() = 0;
        // 从缓冲区读取所有的数据以字符串形式返回
        virtual std::string GetAsString(size_t len) = 0;
    };

    // 定义一个协议层来解析消息中的各个元素的含义
    // 把信息通过自定义协议把消息
    class BaseProtocol
    {
    public:
        using ProPtr = std::shared_ptr<BaseProtocol>;
        // 能否解析该接收的消息
        virtual bool IsDeal(const Abstract::BaseBuffer::BuffPtr &buf) = 0;
        // 把接收的消息中的各个元素解析到message对象中去
        virtual bool Analizy_Message(const Abstract::BaseBuffer::BuffPtr &buf, Abstract::BaseMessage::MesaPtr &msg) = 0;
        // 把message对象中消息的各个元素组指并且序列化；
        virtual std::string Serialize( Abstract::BaseMessage::MesaPtr msg) = 0;
    };

    // 提供查询链接和关闭连接的方法还有发送消息的方法
    // 封装每一个链接的客户端
    class BaseConnection
    {
    public:
        // 提供父类的指针类型来接收将来的派生类对象
        using ConPtr = std::shared_ptr<BaseConnection>;
        // 负责发送消息
        virtual void Send(Abstract::BaseMessage::MesaPtr msg) = 0;
        virtual void ShutDown() = 0;  // 关闭连接
        virtual bool IsConnect() = 0; // 查询链接状态
    };

    // 服务器抽象类--负责提供启动服务器的接口
    // 设置连接成功时的回调函数，链接断开时的回调函数，fd读就绪事件的回调函数
    // 把链接对象传入进去
    using Connection_CallBack = std::function<void(const BaseConnection::ConPtr &)>;
    using Close_CallBack = std::function<void(const BaseConnection::ConPtr &)>;
    using Ready_CallBack = std::function<void(const Abstract::BaseConnection::ConPtr &, const Abstract::BaseMessage::MesaPtr &)>;
    class BaseServer
    {
    public:
        using SerPtr = std::shared_ptr<BaseServer>;
        virtual void start() = 0;
        virtual void SetConnection_CallBack(Connection_CallBack ccb)
        {
            _ConCback = ccb;
        }
        virtual void SetClose_CallBack(Close_CallBack ccb)
        {
            _CloCBack = ccb;
        }
        virtual void SetReady_CallBack(Ready_CallBack rcb)
        {
            _ReaCBack = rcb;
        }

    protected:
        Connection_CallBack _ConCback;
        Close_CallBack _CloCBack;
        Ready_CallBack _ReaCBack;
    };
    // 提供 链接服务器(创建套接字)和创建链接对象(负责IO处理的对象)方法
    class BaseClient
    {
    public:
        using SerPtr = std::shared_ptr<BaseClient>;
        virtual void SetConnection_CallBack(Connection_CallBack ccb)
        {
            _ConCback = ccb;
        }
        virtual void SetClose_CallBack(Close_CallBack ccb)
        {
            _CloCBack = ccb;
        }
        virtual void SetReady_CallBack(Ready_CallBack rcb)
        {
            _ReaCBack = rcb;
        }
        // 判断链接状态
        virtual bool IsConnect() = 0;
        // 链接服务器
        virtual void ConnectServer() = 0;
        // 关闭连接
        virtual void Shutdown() = 0;
        // 发送数据
        virtual void Send( Abstract::BaseMessage::MesaPtr Mptr) = 0;
        // 获取链接对象-负责io处理的对象
        virtual Abstract::BaseConnection::ConPtr GetConnection() = 0;

    protected:
        Connection_CallBack _ConCback;
        Close_CallBack _CloCBack;
        Ready_CallBack _ReaCBack;
    };
};
